<script setup>
import { reactive, ref, onMounted, computed, nextTick, watchEffect, watch  } from 'vue';

// 混剪 公共参数配置
import {
  // 计算可拖拽区域的宽高比例
  calculateDraggableArea
} from "@/common/utils/richTextProcessing.js";

// 工具
import GTC_tools from "@/views/shotstack/utils/helper.js";

import { useStore } from "vuex";
import { message } from 'ant-design-vue';

// 加载中icon
import { LoadingOutlined } from '@ant-design/icons-vue';
import Konva from 'konva';
// import { defineComponent, h } from 'vue';

// 仓库
const store = useStore();

const emit = defineEmits(['update_position', 'update_stickers'])
const props = defineProps({
  // 当前编辑的项
  editItem: {
    type: Object,
    default: () => {
        return {}
    }
  },

  // 当前分辨率
  pixel: {
    type: Object,
    default: () => {
        return null
    }
  },

  // 当前素材列表
  images: {
    type: Array,
    default: () => {
        return []
        }
  },

    // 当前贴纸列表
    stickers: {
        type: Array,
        default: () => {
            return []
        }
    },

  // 当前选择的图片模板
  image_tpl: {
    type: String,
    default: () => ''
    },

    // 是不是预览 -- 预览会隐藏 一些拖拽边框效果
    isView: {
      type: Boolean,
      default: false
    },

    // 只有在合成预览列表 才会有 parent_id(组的id)
    parent_id: {
        type: Number,
        default: () => null
    },

    // 只有在合成预览列表 才会有 sort(组的排序值)
    sort: {
        type: Number,
        default: () => 0
    }
})

// 主标题text
const mainTitleRef = ref()

// 主标题 包裹边框
const mainTitleRectRef = ref()

// 副标题text
const deputyTitleRef = ref()

// 副标题 包裹边框
const deputyTitleRectRef = ref()

// canvas画布实例
const stageRef = ref()

// 花字列表
const flowerList = computed(() => {
  return store.state.GraphicTextMixCut.flowerList
});

// 编辑的项
const editItem = computed({
  get() {
    return props.editItem
  },
  set(val) {
    console.log(val, '修改了!!!!!');
  }
})

const state = reactive({
    // 画布容器的大小
    configKonva: {
        height: 640,
        width: 360,
      },

    // 背景图片数据
    showImgs: [],

    // 贴纸渲染数据
    showStickers:[],
        
    initLoding:false
    
})

// 鼠标移入事件
const mouseover = () => {
    console.log('mouseover');
    
    const dom = document.querySelector('.cavas_box')
    dom && (dom.style.cursor = 'move')
}

// 鼠标移出事件
const mouseout = () => {
    console.log('mouseout');

    const dom = document.querySelector('.cavas_box')
    dom && (dom.style.cursor = 'default')
}

// 标题拖拽事件
const dragend = (e, key='main') => {
    console.log('拖拽结束了', e.target?._lastPos);
    const lastPos = e.target?._lastPos
    emit('update_position',{x: lastPos.x, y: lastPos.y, key})
}

// "x": 0,
// "y": 0,
// // 字体
// "font": defaultFont.value.font_family,
// // 花字id
// "font_id": defaultFont.value.id,
// "font_size": 44,

// 主标题 配置项
const mainTitle = computed(() => {
    const main =  editItem.value?.main?.config
        if (!main) return {
            textConfig: {},
            rectConfige: {},
        }
        const find = flowerList.value.find(ele => ele.id == main.flower_id)
        const data = {
            textConfig: {
            fontSize: main.font_size,
            x: main.x,
            y: main.y,
            fontFamily: main.font,
            text: editItem.value?.main?.content,
            // 通过花字id, 赋值的样式
            fill: find?.fontcolor || '#FFFFFF', // 文字颜色,
            stroke: find?.bordercolor || 'transparent', // 文字描边
            // 描边宽度
            strokeWidth:1
            },
            rectConfige: {
                fill: find?.boxcolor || "transparent", // 文字容器背景色
                strokeWidth:1
            }
        }
        // console.log(data, find, '字符的结果');
        return data
});

// 副标题 配置项
const deputyTitle = computed(() => {
    const deputy =  editItem.value?.deputy?.config
        if (!deputy) return {
            textConfig: {},
            rectConfige: {},
        }
        const find = flowerList.value.find(ele => ele.id == deputy.flower_id)
        const data = {
            textConfig: {
            fontSize: deputy.font_size,
            x: deputy.x,
            y: deputy.y,
            fontFamily: deputy.font,
            text: editItem.value?.deputy?.content,
            // 通过花字id, 赋值的样式
            fill: find?.fontcolor || '#FFFFFF', // 文字颜色,
            stroke: find?.bordercolor || 'transparent', // 文字描边
            // 描边宽度
            strokeWidth:1
            },
            rectConfige: {
                fill: find?.boxcolor || "transparent", // 文字容器背景色
                strokeWidth:1
            }
        }
        // console.log(data, find, '字符的结果');
        return data
});

// 切割数组方法
function getFirstElements(arr, num) {
    if (!Array.isArray(arr)) {
        return [];
    }
    num = num === undefined? arr.length : num;
    num = Math.min(num, arr.length);
    return arr.slice(0, num);
}

// 渲染图片方法
const renderImg = (params) => { 
    const {item, index} = params
    const image = new Image();
    // 设置跨域属性
    image.crossOrigin = 'anonymous';
    
    // 排列的模式
    const image_tpl = props.image_tpl

    // 画布的宽高
    const canvasH = state.configKonva.height
    const canvasW = state.configKonva.width

    image.src = item.material_url
    // image.src = item.material_url + `?v=${new Date().valueOf()}`
    return new Promise((resolve, reject) => {
        image.onload = () => {
            const imgWidth = image.width;
            const imgHeight = image.height;
            // 图片的等比例高度
            const aspectRatio = imgWidth / imgHeight;
            // debugger
            let x
            let y
            let w
            let h
    if (image_tpl == 'single_image') {
        // 单图
            x = 0
            y = 0
            // 宽度拉满
        w = canvasW
        // 根据宽高比和容器宽度计算容器高度（即图片缩放后高度）
        const containerHeight = 360 / aspectRatio;
        // 高度为等比例高度
        h = containerHeight < canvasH ? containerHeight : canvasH;
        const targetRatio = w / h;  // 目标区域（画布划分区域）宽高比
        // 修改 canvas的高度也为这个值
        state.configKonva.height = h
        GTC_tools.calculateFn({
            item, x, y, w, h, image_tpl, aspectRatio, targetRatio,imgWidth, imgHeight, image
        })
    } else if (
        image_tpl == 'couple_image_9_16'
        || image_tpl == 'couple_image_16_9'
        || image_tpl == 'couple_image_1_1'
    ) {
        // 两图
        w = canvasW / 2
        h = canvasH;
        const targetRatio = w / h;  // 目标区域（画布划分区域）宽高比
        if (index == 0) {
            x = 0
            y = 0
        } else if (index == 1) {
            x = canvasW / 2
            y = 0
        }
        GTC_tools.calculateFn({ item, x, y, w, h, image_tpl, aspectRatio, targetRatio, imgWidth, imgHeight, image })
    } else if (image_tpl == 'four_image_9_16' || image_tpl == 'four_image_1_1') {
        // 四图
        w = canvasW / 2
        h = canvasH / 2;
        const targetRatio = w / h;  // 目标区域（画布划分区域）宽高比
        if (index == 0) {
            x = 0
            y = 0
        } else if (index == 1) {
            x = canvasW / 2
            y = 0
        } else if (index == 2) {
            x = 0
            y = canvasH / 2
        } else if (index == 3) {
            x = canvasW / 2
            y = canvasH / 2
        }
        GTC_tools.calculateFn({ item, x, y, w, h, image_tpl, aspectRatio, targetRatio, imgWidth, imgHeight, image })
  }            
            resolve()
        }
    });
}

/**
* @param {
  * 图片模版 
  * single_image: 单图; 
  * couple_image_9_16: 2图9:16; 
  * couple_image_16_9: 2图16:9;
  * couple_image_1_1: 2图1:1;
  * four_image_9_16: 4图9:16;
  * four_image_1_1: 4图1:1;
* } image_tpl
*  */
const renderImgFn = async () => {

return new Promise(async (resolve, reject) => {

try {
    const image_tpl = props.image_tpl
    const images = props.images
    let arr = []
    if (image_tpl == 'single_image') {
        if (images?.[0]) {
            await renderImg({
            item: images[0],
            index:0
        })
            arr[0] = images[0]
        }

        state.showImgs = arr
        resolve(arr || [])
        return arr || []
  } else if (
       image_tpl == 'couple_image_9_16'
    || image_tpl == 'couple_image_16_9'
    || image_tpl == 'couple_image_1_1'
  ) {
        arr = getFirstElements(images, 2)
  } else if (image_tpl == 'four_image_9_16' || image_tpl == 'four_image_1_1') {
    arr = getFirstElements(images, 4)
    }

    for (let i = 0; i < arr.length; i++) {
        await renderImg({
            item: arr[i],
            index:i
        })
    }
    state.showImgs = arr
    resolve(arr || [])
        } catch (error) {
            console.log('renderImgFn失败了', error);
            reject('err')
            
        }
   
    });
}

// 贴纸列表
const stickerTransformers = ref([])

// 贴纸图层
const stickerLayer = ref()

// 贴纸被拖拽, 放大缩小后的 更新函数
const updateStickerStatus = (imgItem) => {
    const data = {
        x:imgItem.x(),
        y:imgItem.y(),
        rotation: imgItem.rotation(),
        width:imgItem.width(),
        height:imgItem.height(),
        scaleX:imgItem.scaleX(),
        scaleY:imgItem.scaleY()
    }

    const id = imgItem?.attrs?.id.split('_')[0]

    const cloneStickers = JSON.parse(JSON.stringify(props.stickers))

    const find = cloneStickers.find(ele => ele.id == id)
    if (find) {
        Object.assign(find, data)
        emit('update_stickers', cloneStickers)
    }

    // console.log(data, imgItem, '贴纸数据更新');
}

// 渲染 贴纸img dom数据
const renderStickersImgDomFn = (params={}) => {
    const { item } = params
    const image = new Image();
    // 设置跨域属性
    image.crossOrigin = 'anonymous';

    image.src = item.material_url

    // 画布的宽高
    const canvasH = state.configKonva.height
    const canvasW = state.configKonva.width

    return new Promise((reslove, reject) => {
        image.onload = () => {
            // debugger
            const imgWidth = item?.width || image.width;
            const imgHeight = item?.height || image.height;
            // const imgWidth = image.width;
            // const imgHeight = image.height;
            // 图片的等比例高度
            const aspectRatio = imgWidth / imgHeight;

            let newWidth = imgWidth, newHeight = imgHeight;

            // 等比例 缩放图片, 使图片宽高不超过容器
            if (newWidth > canvasW) {
                newWidth = canvasW;
                newHeight = canvasW / aspectRatio;
            } 
            
            if (newHeight > canvasH) {
                newHeight = canvasH;
                newWidth = canvasH * aspectRatio;
            }

            var imgItem = new Konva.Image({
                image,
                draggable: true,
                width: newWidth,
                height: newHeight,
                x:item.x,
                y: item.y,
                rotation: item?.rotation || 0,
                scaleX: item?.scaleX || 1,
                scaleY: item?.scaleY || 1,
                id: item.id + '_img',
            });


            imgItem.on('dragstart',function () {
                const stickerLayerDom = stickerLayer.value?.getNode()
                if (stickerLayerDom) {
                    this.moveToTop();
                //     const cloneStickers = JSON.parse(JSON.stringify(props.stickers))
                //     const id = imgItem?.attrs?.id.split('_')[0]
                //    const index = cloneStickers.findIndex(ele => ele.id == id)
                //     if (index != -1) {
                //         nextTick(() => {                      
                //             cloneStickers.push(cloneStickers.splice(index, 1)[0])
                //             console.log(cloneStickers,'改变层级调用');
                            
                //             emit('update_stickers', cloneStickers)
                //             stickerLayerDom.draw()
                //         })
                //    }
                }
            });

        //     imgItem.on('mouseover',function () {
        //         const stickerLayerDom = stickerLayer.value?.getNode()
        //         if (stickerLayerDom) {
        //                     // 或者添加一个边框
        //                 this.stroke('red');
        //             this.strokeWidth(1);
        //                     stickerLayerDom.draw()
                        
        //         }
        //     });

        //     imgItem.on('mouseout',function () {
        //         const stickerLayerDom = stickerLayer.value?.getNode()
        //         if (stickerLayerDom) {
        //              // 移除边框
        // this.stroke(null);
        // this.strokeWidth(0);
        // stickerLayerDom.draw();
        //         }
        //     });

            imgItem.on('dragmove', () => updateStickerStatus(imgItem));

            imgItem.on('transform', () => updateStickerStatus(imgItem));

           let tr = new Konva.Transformer({
            anchorStroke:props.isView ? 'transparent' : '#1890ff',
            anchorFill: props.isView ? 'transparent' : '#1890ff',
            anchorSize: 8,
            borderStroke: props.isView ? 'transparent' : '#1890ff',
            borderDash: [3, 3],
            nodes: [imgItem],
            id: item.id + '_transformer',
           });

           const stickerLayerDom = stickerLayer.value?.getNode()
           
            if (stickerLayerDom) {
                stickerLayerDom.add(imgItem);
                stickerLayerDom.add(tr);
           }
           reslove()
        }
    })
}

// 渲染贴纸数据
const renderStickers = (list) => {
    
    return new Promise(async(reslove, reject) => {        
        if (!list.length) {
            reslove()
            return
        }

        for (let i = 0; i < list.length; i++){
            const item = list[i]
            await renderStickersImgDomFn({item})
        }

        reslove()
    })
}

// 删除某项贴纸数据
const delSticker = (item) => {
    // const index = props.stickers.findIndex(ele => ele.id == item.id)
    const stickerLayerDom = stickerLayer.value?.getNode()
        if (stickerLayerDom) {
            const transformer_id = item.id + '_transformer'
            const transformer = stickerLayerDom.find(`#${transformer_id}`)[0];
            transformer?.destroy();

            const img_id = item.id + '_img'
            const img = stickerLayerDom.find(`#${img_id}`)[0];
            img?.destroy();
            
            // 手动触发层的绘制更新
            stickerLayerDom.draw();
        }
    
}

const sizeInit = () => {
    return new Promise((resolve, reject) => {
        try {
            const sizeData = calculateDraggableArea(
            props.pixel?.w,
            props.pixel?.h
        );
        state.configKonva.height = sizeData.draggableHeight
        state.configKonva.width = sizeData.draggableWidth
        resolve(state.configKonva)
        } catch (error) {
            console.log('sizeInit失败了', error);
            reject('err')
        }

    });
}

// 初始化 canvas 的宽高和渲染 拼接背景图
const init = () => {
    
    return new Promise(async (resolve, reject) => {
        console.log('初始化中.......');
        state.initLoding = true
        // 贴纸列表
        state.showStickers = JSON.parse(JSON.stringify(props.stickers))

        try {
            await sizeInit()
            // 渲染背景图片数据
            await renderImgFn()
            // 渲染贴纸数据
            const stickerLayerDom = stickerLayer.value?.getNode()
            if (stickerLayerDom) {
                stickerLayerDom.destroyChildren()
            }
            await renderStickers(state.showStickers)
            
            syncMainWH()
            syncMainWH({ key: 'deputy' })
            resolve('ok')
            // console.log('初始结束---------------');
        
        } catch (error) {
            console.log('初始化失败了', error);
            message.error('绘制失败了,请稍后重试')
            reject('err')
        } finally {
        state.initLoding = false
        }
    })

}

// 同步 文本边框和标题的宽高
const syncMainWH = (params = {}) => {
    /**
     * @param {key: 'main' | 'deputy'}
     */
    const { nv, ov, key = 'main' } = params

    const RectNode = key == 'main' ? mainTitleRectRef.value?.getNode() : deputyTitleRectRef.value?.getNode()
    const TextNode = key == 'main' ? mainTitleRef.value?.getNode() : deputyTitleRef.value?.getNode()

    if (RectNode && TextNode) {
        const width = TextNode.getWidth()
        const height = TextNode.getHeight()
        RectNode.width(width)
        RectNode.height(height + 2)
    }   
}

// 保存图片
const getImgData = (params = {}) => {
    const {pixelRatio=1} = params
    return new Promise((resolve, reject) => {
        try {
                const dom = stageRef.value?.getNode()
                console.log(dom, '画布实例??');
                const res =  dom.toDataURL({
                pixelRatio // or other value you need
                })
            console.log(res, '绘制结果??');
            resolve({
                res,
                parent_id: props.parent_id,
                sort: props.sort,
            })
        } catch (error) {
            resolve(null)
        }
    })
}

// 获取偏移值
const getOffsetY = (fontFamily) => {
    if (fontFamily == 'Yuanti SC') {
        // 圆体-简常规体
        return 1.5
    }else if (fontFamily == 'FZHei-B01S') {
        // 方正黑体简体
        return -4
    } else if (fontFamily == 'FZShuSong-Z01S') {
        // 方正书宋简体
        return -4
    }else if (fontFamily == 'SimSun') {
        // 宋体, 文泉驿系列
        return -1
    } else if (fontFamily == 'WenQuanYi MicroHei' || fontFamily == 'WenQuanYi Zen Hei Mono' || fontFamily == 'WenQuanYi Zen Hei Sharp') {
        // 文泉驿系列
        return -2
    } else if (fontFamily == 'Microsoft YaHei') {
        // 微软雅黑
        return -4
    }  else if (fontFamily == 'Roboto Bold' || fontFamily == 'Roboto') {
        // 谷歌系列
        return -3
    } else if (fontFamily == 'Alibaba PuHuiTi') {
        // 阿里巴巴 普惠体
        return -1
    }   else if (fontFamily == 'SiYuan Heiti' || fontFamily == 'SiYuan SimSun') {
        // 思源系列
        return -1
    } else {
        return -2
    }
}

// 同步更新主标题边框和宽高
watch(() => mainTitle.value?.textConfig, (nv, ov) => {
    // console.log(nv, '文本节点发生了变化');
    nextTick(() => {
        syncMainWH({nv,ov})
    })
})
watch(() => deputyTitle.value?.textConfig, (nv, ov) => {
    // console.log(nv, '文本节点发生了变化');
    nextTick(() => {
        syncMainWH({nv,ov, key: 'deputy'})
    })
})

onMounted(() => {
    init()
})

defineExpose({
    init,
    getImgData,
    renderStickers,
    delSticker
})

</script>

<template>
    <div class="konvaCount">

         <div class="konva_loding" v-if="state.initLoding">
            <LoadingOutlined  class="icon_loding"/>
         </div>
        <div class="cavas_box">
            <v-stage  ref="stageRef" :config="{
            ...state.configKonva
            }" v-if="Array.isArray(state.showImgs)">
            <template >       
            <v-layer ref="layer" 
                :config="{
                    // width: state.configKonva.width,
                    // height: state.configKonva.height,
                }">
                    <v-image 
                    v-for="item in state.showImgs"
                    :config="item?.Imgconfig || {}" 
                    />
            </v-layer>

            <v-layer :config="{
                // width: state.configKonva.width,
                // height: state.configKonva.height,
            }">

            <!-- 主标题 -->
        <v-group 
            @mouseover="mouseover"
            @mouseout="mouseout"
            @dragend="$event => dragend($event, 'main')"
            :config="{
                x: mainTitle.textConfig.x,
                y: mainTitle.textConfig.y,
                draggable: true,
            }">
                <v-rect 
                ref="mainTitleRectRef"
                :config="{
                    fill: mainTitle.rectConfige.fill,  // 设置为透明填充
                    stroke: props.isView ? 'transparent' : '#1890ff',  // 边框颜色
                    strokeWidth: mainTitle.rectConfige.strokeWidth,  // 边框宽度
                    dash: [4, 2]  // 设置虚线样式，线段长2像素，间隔2像素
                }"
                ></v-rect>
            <v-text
            ref="mainTitleRef"
            :config="{
                fontSize: mainTitle.textConfig.fontSize,
                text: mainTitle.textConfig.text,
                fill: mainTitle.textConfig.fill,
                lineHeight: 1.1,
                // 偏移值
                offsetY: getOffsetY(mainTitle.textConfig.fontFamily),
                // 文字描边
                stroke: mainTitle.textConfig.stroke,
                // 描边宽度
                strokeWidth:mainTitle.textConfig.strokeWidth,
                fontFamily: mainTitle.textConfig.fontFamily,
        }" />
        </v-group>
        
        <!-- 副标题 -->
        <v-group 
        v-if="editItem?.deputy?.config"
            @mouseover="mouseover"
            @mouseout="mouseout"
            @dragend="$event => dragend($event, 'deputy')"
            :config="{
                x: deputyTitle.textConfig.x,
                y: deputyTitle.textConfig.y,
                draggable: true,
            }">
                <v-rect 
                ref="deputyTitleRectRef"
                :config="{
                    fill: deputyTitle.rectConfige.fill,  // 设置为透明填充
                    stroke: props.isView ? 'transparent' : '#1890ff',  // 边框颜色
                    strokeWidth: deputyTitle.rectConfige.strokeWidth,  // 边框宽度
                    dash: [4, 2]  // 设置虚线样式，线段长2像素，间隔2像素
                }"
                ></v-rect>
            <v-text
            ref="deputyTitleRef"
            :config="{
                fontSize: deputyTitle.textConfig.fontSize,
                text: deputyTitle.textConfig.text,
                fill: deputyTitle.textConfig.fill,
                lineHeight: 1.1,
                offsetY: -1,
                // 文字描边
                stroke: deputyTitle.textConfig.stroke,
                // 描边宽度
                strokeWidth: deputyTitle.textConfig.strokeWidth,
                // 字体
                fontFamily: deputyTitle.textConfig.fontFamily,
        }" />
        </v-group>

        <!-- 贴纸 -->
        <!-- @dragend="$event => dragend($event, 'deputy')" -->
            </v-layer>

            <v-layer 
            ref="stickerLayer"
            :config="{
                // width: state.configKonva.width,
                // height: state.configKonva.height,
            }"> 
        </v-layer>

            </template>
                </v-stage>
            </div>
    </div>
</template>

<style lang="less" scoped>
    .konvaCount{
        // background-color: #fff;
        // background-color: #222222;
        background-color: #000;
    //    padding: 10px;
        // border-radius: 20px;
        // overflow: hidden;
        position: relative;

        // canvas -- 加载中
        .konva_loding{
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-color: #00000062;
            z-index: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            .icon_loding{
                font-size: 80px;
                color: var(--ss-primary-color-hover);
            }
        }

        .title_box{
            margin-bottom: 10px;
            font-size: 14px;
            font-weight: 600;
            padding: 10px;
        }

        .cavas_box{
            height: 640px;
            width: 360px;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        
    }
</style>